#ifndef LEAMLOMMESSAGEHH
#define LEAMLOMMESSAGEHH
#include "leam-lom-enums.hh"
#include "leam-data-out-stream.hh"

namespace leam_lom
{
    /**
       This describes the leam-lom message format.  Each enumeration has a
       distinct message associated with it.  These structs are not
       necessarily ever created, they are just to ensure that it is easy
       to understand the leam-lom communication system.

       There are only a few odd pieces.  The first is handle-negotiation.
       Because the handle-generation systems of the two lom systems could
       generate the same handle, the stream has to communicate in a language
       that avoids handle-collision.

       The way I decided to do this is that the sender speaks in its terminology.
       When it creates a new handle alias, it sends this alias before it uses
       the alias so that the other stream can correctly decode the information.

       Lets say that you have two entities, A and B connected to each other.
       When A sends an instance to B, A tells B what handle it is going to use
       in further communication, and B tells A what its alias is for the handle.
       When B detects a handle it hasn't seen before, all it does is ensure that
       the next time it communicates with A, it tells A what alias it is using 
       for the new handle.  Thus A should be able to correctly decode the handles
       back to its own language.

       You have basically two possibilities on the sending side.  If you are
       sending an instance, you send the handle you are going to use for the instance
       before you send the instance.

       If you are sending a handle, you just send the handle.  If the
       receiver has not seen the handle yet, it will create an alias
       for an instance that it has not seen yet (i.e. reserve a
       handle).  When it sees the instance, it will create it with the
       correct reference count.
       
       ELeamLomMessageType is 1 byte.
       All data is in the lom binary format.
    */
    struct LeamLomEvent //ELeamLomMessageTypeEvent
    {
	licada::TNameStr name
	lom::TDataVector data;
    };
    
    /**
       If the class has already been created, this should update the
       class with the new class definition.
     */
    struct LeamLomClassCreated //ELeamLomMessageTypeClass
    {
	const lom::LomClass* cls
    };
    
    /**
       If the instance has already been created (handles will match),
       this should update the instance with the new instance
       definition
     */
    struct LeamLomInstanceCreated //ELeamLomMessageTypeInstanceCreated
    {
	lom::THandle handle;
	const lom::LomInstance* inst;
    };
    
    struct LeamLomInstanceDestroyed //ELeamLomMessageTypeInstanceDestroyed
    {
	lom::THandle handle;
    };
    
    struct LeamLomInstanceProperty //ELeamLomMessageTypeInstanceProperty
    {
	lom::THandle handle;
	licada::uint32 index;
	const lom::LomValue* lomValue;
    };
    
    struct LeamLomRootObject //ELeamLomMessageTypeRootObject
    {
	licada::TNameStr name;
	const lom::LomValue* lomValue;
    };
    
    /**
       This is from the point of view of the receiver.  The handle
       names are reversed if you are the sender.
    */
    struct LeamLomHandleMap //ELeamLomMessageTypeHandleMap
    {
	lom::THandle streamHandle;
	lom::THandle worldHandle;
    };
}

#endif
